/**
 * Animation - 动画类
 * 处理帧动画的播放、循环和状态管理
 */

import { Sprite } from './Sprite'

export interface AnimationFrame {
  frameIndex: number
  duration: number // 帧持续时间（毫秒）
}

export interface AnimationOptions {
  name: string
  sprite: Sprite
  frames: AnimationFrame[]
  loop?: boolean
  autoPlay?: boolean
  speed?: number // 播放速度倍数，1.0为正常速度
}

export enum AnimationState {
  STOPPED = 'stopped',
  PLAYING = 'playing',
  PAUSED = 'paused',
  FINISHED = 'finished'
}

export class Animation {
  public readonly name: string
  public readonly sprite: Sprite
  public readonly frames: AnimationFrame[]
  public readonly loop: boolean
  public readonly speed: number

  private currentFrameIndex: number = 0
  private currentTime: number = 0
  private state: AnimationState = AnimationState.STOPPED
  private onCompleteCallback?: () => void
  private onFrameChangeCallback?: (frameIndex: number) => void

  constructor(options: AnimationOptions) {
    this.name = options.name
    this.sprite = options.sprite
    this.frames = options.frames
    this.loop = options.loop !== false // 默认循环
    this.speed = options.speed || 1.0

    if (options.autoPlay) {
      this.play()
    }
  }

  /**
   * 播放动画
   */
  play(): void {
    if (this.state === AnimationState.FINISHED && !this.loop) {
      this.reset()
    }
    this.state = AnimationState.PLAYING
  }

  /**
   * 暂停动画
   */
  pause(): void {
    if (this.state === AnimationState.PLAYING) {
      this.state = AnimationState.PAUSED
    }
  }

  /**
   * 停止动画
   */
  stop(): void {
    this.state = AnimationState.STOPPED
    this.reset()
  }

  /**
   * 重置动画到第一帧
   */
  reset(): void {
    this.currentFrameIndex = 0
    this.currentTime = 0
    this.updateSpriteFrame()
  }

  /**
   * 更新动画
   */
  update(deltaTime: number): void {
    if (this.state !== AnimationState.PLAYING || this.frames.length === 0) {
      return
    }

    this.currentTime += deltaTime * this.speed
    const currentFrame = this.frames[this.currentFrameIndex]

    if (this.currentTime >= currentFrame.duration) {
      this.currentTime = 0
      this.nextFrame()
    }
  }

  /**
   * 渲染动画
   */
  render(
    ctx: CanvasRenderingContext2D,
    x: number,
    y: number,
    width?: number,
    height?: number
  ): void {
    this.sprite.render(ctx, x, y, width, height)
  }

  /**
   * 获取当前状态
   */
  getState(): AnimationState {
    return this.state
  }

  /**
   * 获取当前帧索引
   */
  getCurrentFrameIndex(): number {
    return this.currentFrameIndex
  }

  /**
   * 获取动画总时长
   */
  getTotalDuration(): number {
    return this.frames.reduce((total, frame) => total + frame.duration, 0)
  }

  /**
   * 获取动画进度（0-1）
   */
  getProgress(): number {
    if (this.frames.length === 0) return 0
    
    let elapsed = 0
    for (let i = 0; i < this.currentFrameIndex; i++) {
      elapsed += this.frames[i].duration
    }
    elapsed += this.currentTime
    
    return Math.min(elapsed / this.getTotalDuration(), 1)
  }

  /**
   * 设置完成回调
   */
  onComplete(callback: () => void): void {
    this.onCompleteCallback = callback
  }

  /**
   * 设置帧变化回调
   */
  onFrameChange(callback: (frameIndex: number) => void): void {
    this.onFrameChangeCallback = callback
  }

  /**
   * 跳转到指定帧
   */
  gotoFrame(frameIndex: number): void {
    if (frameIndex >= 0 && frameIndex < this.frames.length) {
      this.currentFrameIndex = frameIndex
      this.currentTime = 0
      this.updateSpriteFrame()
      
      if (this.onFrameChangeCallback) {
        this.onFrameChangeCallback(frameIndex)
      }
    }
  }

  /**
   * 检查动画是否正在播放
   */
  isPlaying(): boolean {
    return this.state === AnimationState.PLAYING
  }

  /**
   * 检查动画是否已完成
   */
  isFinished(): boolean {
    return this.state === AnimationState.FINISHED
  }

  /**
   * 下一帧
   */
  private nextFrame(): void {
    const oldFrameIndex = this.currentFrameIndex
    this.currentFrameIndex++

    if (this.currentFrameIndex >= this.frames.length) {
      if (this.loop) {
        this.currentFrameIndex = 0
      } else {
        this.currentFrameIndex = this.frames.length - 1
        this.state = AnimationState.FINISHED
        
        if (this.onCompleteCallback) {
          this.onCompleteCallback()
        }
      }
    }

    this.updateSpriteFrame()

    // 触发帧变化回调
    if (oldFrameIndex !== this.currentFrameIndex && this.onFrameChangeCallback) {
      this.onFrameChangeCallback(this.currentFrameIndex)
    }
  }

  /**
   * 更新精灵的当前帧
   */
  private updateSpriteFrame(): void {
    if (this.frames.length > 0) {
      const animFrame = this.frames[this.currentFrameIndex]
      this.sprite.setFrame(animFrame.frameIndex)
    }
  }

  /**
   * 创建简单的循环动画
   */
  static createLoop(
    name: string,
    sprite: Sprite,
    frameDuration: number,
    frameCount?: number
  ): Animation {
    const count = frameCount || sprite.getFrameCount()
    const frames: AnimationFrame[] = []
    
    for (let i = 0; i < count; i++) {
      frames.push({
        frameIndex: i,
        duration: frameDuration
      })
    }

    return new Animation({
      name,
      sprite,
      frames,
      loop: true
    })
  }

  /**
   * 创建单次播放动画
   */
  static createOnce(
    name: string,
    sprite: Sprite,
    frameDuration: number,
    frameCount?: number
  ): Animation {
    const count = frameCount || sprite.getFrameCount()
    const frames: AnimationFrame[] = []
    
    for (let i = 0; i < count; i++) {
      frames.push({
        frameIndex: i,
        duration: frameDuration
      })
    }

    return new Animation({
      name,
      sprite,
      frames,
      loop: false
    })
  }
}